#include <iostream>  
#include <memory>  
#include <string>  
  
class Product {  
private:  
    std::string partA_;  
    std::string partB_;  
    std::string partC_;  
public:  
    Product() : partA_(""), partB_(""), partC_("") {}  
  
    std::string getPartA() const { return partA_; }  
    std::string getPartB() const { return partB_; }  
    std::string getPartC() const { return partC_; }  
  
    void setPartA(std::string part) { partA_ = part; }  
    void setPartB(std::string part) { partB_ = part; }  
    void setPartC(std::string part) { partC_ = part; }  

    friend std::ostream& operator<<(std::ostream& os, const Product& product){  
        os << "partA :" << product.partA_ << "\t" << "partB:" << product.partB_ << "\t" << "partC:" << product.partC_ << "\n";  
        return os;  
    }
};  


class Builder {  
protected:  
    Product* product_;  
public:  
    Builder() : product_(new Product()) {}  
    virtual ~Builder() { delete product_; }  
    virtual void BuildPartA(std::string part) = 0;  
    virtual void BuildPartB(std::string part) = 0;  
    virtual void BuildPartC(std::string part) = 0;  
    Product* getResult() const { return product_; }  
};  
  
class ConcreteBuilder : public Builder {  
public:  
    ConcreteBuilder() : Builder() {}  
    void BuildPartA(std::string part) override { product_->setPartA(part); }  
    void BuildPartB(std::string part) override { product_->setPartB(part); }  
    void BuildPartC(std::string part) override { product_->setPartC(part); }  
};  
  
class Director {  
private:  
    Builder* builder_;  
public:  
    Director(Builder* builder) : builder_(builder) {}  
    void setBuilder(Builder* builder) { builder_ = builder; }  
    Builder* getBuilder() const { return builder_; }  
  
    Product* construct(std::string partA, std::string partB, std::string partC) {  
        builder_->BuildPartA(partA);  
        builder_->BuildPartB(partB);  
        builder_->BuildPartC(partC);  
        return builder_->getResult();  
    }  
};  
  
int main() {  
    std::unique_ptr<Builder> builder = std::make_unique<ConcreteBuilder>();  
    Director director(builder.get());  
    Product* product = director.construct("AAAAA", "BBBBBBBBB", "CCCCCCCCC");  
  
    std::cout << *product;  
    return 0;  
}